/**
 * zdom - facade on top of W3C DOM API
 */

/**
 * Factory for znode objects
 * @param {String} selectorOrMarkup
 * @param {Object} attributes
 * @returns {ZNode} ZNode object
 */

zdom = (function () {

    /**
     * Create ZNode object,
     * all methods of znode object should be chainable
     * @param {String} selectorOrMarkup
     * @param {Object} attributes
     * @constructor
     */

    var ZNode = function (selectorOrMarkup, attributes) {

        this.el = null;

        if (!attributes) {
            this.el = document.querySelector(selectorOrMarkup);
        } else {
            if (typeof (selectorOrMarkup) === "string" && !(selectorOrMarkup.indexOf('<') === -1) && !(selectorOrMarkup.indexOf('>') === "-1") ) {

                var posTagStart = selectorOrMarkup.indexOf('<') + 1;
                var posTagEnd = selectorOrMarkup.indexOf('>');
                var tag = selectorOrMarkup.slice(posTagStart, posTagEnd);

                // check the string
                var posTagEndLast = selectorOrMarkup.lastIndexOf('>');
                var posTagStartLast = selectorOrMarkup.lastIndexOf('<') + 1;
                var tagClosing = selectorOrMarkup.slice(posTagStartLast, posTagEndLast);

                if (tag === tagClosing) {
                    var _el = document.createElement(tag);
                    _el.innerHTML = selectorOrMarkup.slice(posTagEnd + 1, posTagStartLast + 1);
                    if (typeof attributes === "object") {
                        for (var prop in attributes) {
                            _el.setAttribute(prop, attributes[prop]);
                        }

                    }
                    this.el = _el;
                };

            }
        }

    };

    /**
     * Set attribute for dom node
     * @param {String} name
     * @param {String} value
     * @returns {ZNode}
     */

    ZNode.prototype.attr = function (name, value) {

        this.el.setAttribute(name, value);
        return this;

    };

    /**
     * Set attribute for dom node
     * @param {String} name
     * @returns {ZNode}
     */

    ZNode.prototype.removeAttr = function (name) {

        this.el.removeAttribute(name, "");
        return this;

    };


    /**
     * Hide given element  from UI
     * @param {Number} delay - in milliseconds, 0 by default
     */

    ZNode.prototype.hide = function (delay) {
        var _delay = delay || 0,
            start = new Date,
            self = this;

        if (_delay) {
            var timer = setInterval( function() {

                // animation state
                var progress = Math.round((( new Date - start ) / _delay) * 1000 ) / 1000;
                if (progress > 1) progress = 1;

                // draw animation
                opcAnimate =  Math.round ((1 - progress) * 100) / 100;

                // finish
                if ( opcAnimate <= 0 ) {
                    self.el.setAttribute("display", "none")
                    clearInterval(timer);
                }

                self.el.setAttribute("opacity", opcAnimate);

                }, 40 // frame every 40ms
            );
        } else {
            self.el.setAttribute("display", "none")
        }

        return this;
    };


    /**
     * Show given element on UI
     * @param {Number} delay - in milliseconds, 0 by default
     */

    ZNode.prototype.show = function (delay) {

        var _delay = delay || 0,
            start = new Date,
            self = this;

        self.el.setAttribute("display", "block");

        if (_delay) {
            var timer = setInterval( function() {

                // animation state
                var progress = Math.round((( new Date - start ) / _delay) * 1000 ) / 1000;
                if (progress > 1) progress = 1;

                // draw animation
                opcAnimate =  Math.round (progress * 100) / 100;

                // finish
                if ( opcAnimate >= 1 ) {
                    clearInterval(timer);
                }

                self.el.setAttribute("opacity", opcAnimate);

                }, 40 // frame every 40ms
            );
        }

        return this;
    };

    /**
     * Show given element on UI
     * @param {Number} delay - in milliseconds, 0 by default
     */

    ZNode.prototype.slideDown = function (delay) {

        var _delay = delay || 0,
            start = new Date,
            self = this,
            height = this.el.offsetHeight;

        self.el.setAttribute("display", "block");

        if (_delay) {
            var timer = setInterval( function() {

                // animation state
                var progress = Math.round(((new Date - start) / _delay) * 1000 ) / 1000;
                if (progress > 1) progress = 1;

                // draw animation
                heightAnimate =  Math.round (progress * 100) / 100;

                // finish
                if ( heightAnimate >= 1 ) {
                    clearInterval(timer);
                }

                self.el.setAttribute("style", "height :" + height * heightAnimate + "px");

                }, 40 // frame every 40ms
            );
        }

        return this;
    };

    /**
    * Create ZNode objects,
    * @param {String} selectorOrMarkup
    * @param {Object} attributes
    */

    var factory = function (selectorOrMarkup, attributes) {

        return new ZNode(selectorOrMarkup, attributes);

    };

    factory.ZNode = ZNode;

    return factory;

})();

// var obj = zdom("<p> <b> Create </b> \"something\" <p>",
//     {
//         "class" : "someDiv"
//     }
// );
// document.body.appendChild(obj.el);

// obj.slideDown(2000);
